package tests;

import static org.junit.Assert.assertTrue;

import java.math.BigInteger;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import components.Decrypter;
import components.Encrypter;
import components.RSAKey;
import components.Rsa;

public class TestRsa {
	Rsa myRsa = new Rsa(4096); //Initialize an Rsa instance, with p and q each using 4 bits.
	RSAKey pubKey = new RSAKey(myRsa.getBigPubKey()[0], myRsa.getBigPubKey()[1]);
	RSAKey privKey = new RSAKey(myRsa.getBigPrivKey()[0], myRsa.getBigPrivKey()[1]);
	
	Encrypter encrypter = new Encrypter();
	Decrypter decrypter = new Decrypter();
	
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Before
	public void setUp() throws Exception {
	}

	@After
	public void tearDown() throws Exception {
	}
	
	@Test
	/**
	 * Iterate through 15 messages then encipher/decipher each of them.
	 * Check for equality between the initial message and the message
	 * returned after the enciphering/deciphering process.
	 */
	public void testEncipherDecipher(){
		System.out.println("Public Key (n, e): (" + pubKey.getN() + ", " + pubKey.getExp() + ")");
		System.out.println("Private Key (n, d): (" + privKey.getN() + ", " + privKey.getExp() + ")");
		
		String[] messages = {"Th is","is", "-a-", "te st", "2", "see", "wh3ther", "0r", 
				"Not", "decipher!ng", "and", "enciphering", "mes$ages", "are", "successful"};

		for(String message : messages){
			System.out.println("Original Plaintext: " + message);

//			double currTime = System.currentTimeMillis();
			BigInteger[] cipherText = encrypter.encipher(message, pubKey);
//			double currTime1 = System.currentTimeMillis();
//			System.out.println(currTime1 - currTime + " to encrypt");
			
//			currTime = System.currentTimeMillis();
			String plainText = decrypter.decipher(cipherText, privKey);
//			currTime1 = System.currentTimeMillis();
//			System.out.println(currTime1 - currTime + " to decrypt");

			System.out.println("Decrypted PlainText: " + plainText);
			assertTrue(message.equals(plainText));
		}
	}
	
	@Test
	/**
	 * Test the time (in milliseconds) it takes to encrypt and decrypt a message of length 10.
	 */
	public void testEncipherDecipherTime(){

		String message = "successful";
		for(int i = 512; i < 4352; i+=256){
			System.out.println("bits = " + i);
			Rsa myRsa = new Rsa(i); //Initialize an Rsa instance, with p and q each using 4 bits.
			RSAKey pubKey = new RSAKey(myRsa.getBigPubKey()[0], myRsa.getBigPubKey()[1]);
			RSAKey privKey = new RSAKey(myRsa.getBigPrivKey()[0], myRsa.getBigPrivKey()[1]);
			
			Encrypter encrypter = new Encrypter();
			Decrypter decrypter = new Decrypter();

			System.out.println("Public Key (n, e): (" + pubKey.getN() + ", " + pubKey.getExp() + ")");
			System.out.println("Private Key (n, d): (" + privKey.getN() + ", " + privKey.getExp() + ")");
			
			double currTime = System.currentTimeMillis();
			BigInteger[] cipherText = encrypter.encipher(message, pubKey);
			double currTime1 = System.currentTimeMillis();
			System.out.println(currTime1 - currTime + " to encrypt");
			
			currTime = System.currentTimeMillis();
			String plainText = decrypter.decipher(cipherText, privKey);
			currTime1 = System.currentTimeMillis();
			System.out.println(currTime1 - currTime + " to decrypt");

			System.out.println("Decrypted PlainText: " + plainText);
			assertTrue(message.equals(plainText));
		}
	}
	

}
